package au.com.handsunited.dao.hibernate;

import java.util.List;

import org.hibernate.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import au.com.handsunited.dao.EntityDAO;
import au.com.handsunited.model.BaseEntity;
import au.com.handsunited.model.BaseEntity;
import au.com.handsunited.model.Group;
import au.com.handsunited.model.Organisation;
import au.com.handsunited.model.Project;
import au.com.handsunited.model.User;
import au.com.handsunited.model.relationship.Relationship;

/**
 * @author arunda
 *
 */
public class EntityDAOHibernate extends HibernateDaoSupport implements EntityDAO {

	private static Logger logger = LoggerFactory.getLogger(EntityDAOHibernate.class);

	/**
	 *
	 */
	public EntityDAOHibernate() {
		super();
	}

	/**
	 * @see au.com.handsunited.dao.impl.EntityDAO#getEntity(java.lang.Long)
	 */
	@Override
	public BaseEntity getEntity(Long id) {
		return (BaseEntity) getHibernateTemplate().get(BaseEntity.class, id);
	}

	/**
	 * @see au.com.handsunited.dao.impl.EntityDAO#getEntity(java.lang.Long, java.lang.Class)
	 */
	@Override
	public BaseEntity getEntity(Long id, Class clazz) {
		return (BaseEntity) getHibernateTemplate().get(clazz, id);
	}


	/**
	 * @see au.com.handsunited.dao.impl.EntityDAO#createEntity(au.com.handsunited.model.BaseEntity)
	 */
	@Override
	public BaseEntity createEntity(BaseEntity entity) {
		getHibernateTemplate().saveOrUpdate(entity);

		if (logger.isDebugEnabled()) {
			logger.debug("{}[{}] added.",
					new String[] {entity.getEntityType(), entity.getName()});
		}
		return entity;
	}


	/**
	 * @see au.com.handsunited.dao.impl.EntityDAO#updateEntity(au.com.handsunited.model.BaseEntity)
	 */
	@Override
	public BaseEntity updateEntity(BaseEntity entity) {
		entity = (BaseEntity) getHibernateTemplate().merge(entity);

		if (logger.isDebugEnabled()) {
			logger.debug("{}[{}] updated.",
					new String[] {entity.getEntityType(), entity.getName()});
		}

		return entity;
	}


	/**
	 * @see au.com.handsunited.dao.EntityDAO#getGroupsInNetworkFor(au.com.handsunited.model.BaseEntity, int, int)
	 */
	public List<Group> getGroupsInNetworkFor(BaseEntity entity, int firstResult, int maxResults) {

		Query q = getNamedQueryWithPagination("Relationships.getGroupsInNetwork", firstResult, maxResults);
		List<Group> groups = q.list();
		return groups;
	}

	/**
	 * @see au.com.handsunited.dao.EntityDAO#getGroupRelationshipsFor(au.com.handsunited.model.BaseEntity, int, int)
	 */
	public List<Relationship> getGroupRelationshipsFor(BaseEntity entity, int firstResult, int maxResults) {
		Query q = getNamedQueryWithPagination("Relationships.getGroupRelationships", firstResult, maxResults);
		List<Relationship> groupRelationships = q.list();
		return groupRelationships;
	}

	/**
	 * @see au.com.handsunited.dao.EntityDAO#getOrganisationsInNetworkFor(au.com.handsunited.model.BaseEntity, int, int)
	 */
	public List<Organisation> getOrganisationsInNetworkFor(BaseEntity entity, int firstResult, int maxResults) {

		Query q = getNamedQueryWithPagination("Relationships.getOrganisationsInNetwork", firstResult, maxResults);
		List<Organisation> organisations = q.list();
		return organisations;
	}


	/**
	 * @see au.com.handsunited.dao.EntityDAO#getOrganisationRelationshipsFor(au.com.handsunited.model.BaseEntity, int, int)
	 */
	public List<Relationship> getOrganisationRelationshipsFor(BaseEntity entity, int firstResult, int maxResults) {
		Query q = getNamedQueryWithPagination("Relationships.getOrganisationRelationships", firstResult, maxResults);
		List<Relationship> organisationRelationships = q.list();
		return organisationRelationships;
	}


	/**
	 * @see au.com.handsunited.dao.EntityDAO#getProjectsInNetworkFor(au.com.handsunited.model.BaseEntity, int, int)
	 */
	public List<Project> getProjectsInNetworkFor(BaseEntity entity, int firstResult, int maxResults) {

		Query q = getNamedQueryWithPagination("Relationships.getProjectsInNetwork", firstResult, maxResults);
		List<Project> organisations = q.list();
		return organisations;
	}

	/**
	 * @see au.com.handsunited.dao.EntityDAO#getProjectRelationshipsFor(au.com.handsunited.model.BaseEntity, int, int)
	 */
	public List<Relationship> getProjectRelationshipsFor(BaseEntity entity, int firstResult, int maxResults) {
		Query q = getNamedQueryWithPagination("Relationships.getProjectRelationships", firstResult, maxResults);
		List<Relationship> projectRelationships = q.list();
		return projectRelationships;
	}

	/**
	 * @see au.com.handsunited.dao.EntityDAO#getUsersInNetworkFor(au.com.handsunited.model.BaseEntity, int, int)
	 */
	public List<User> getUsersInNetworkFor(BaseEntity entity, int firstResult, int maxResults) {

		Query q = getNamedQueryWithPagination("Relationships.getUsersInNetwork", firstResult, maxResults);
		List<User> users = q.list();
		return users;
	}

	/**
	 * @see au.com.handsunited.dao.EntityDAO#getUserRelationshipsFor(au.com.handsunited.model.BaseEntity, int, int)
	 */
	public List<Relationship> getUserRelationshipsFor(BaseEntity entity, int firstResult, int maxResults) {
		Query q = getNamedQueryWithPagination("Relationships.getUserRelationships", firstResult, maxResults);
		List<Relationship> userRelationships = q.list();
		return userRelationships;
	}


	/**
	 *
	 * @param queryName
	 * @param firstResult
	 * @param maxResults
	 * @return
	 */
	private Query getNamedQueryWithPagination (String queryName, int firstResult, int maxResults) {
		Query q = getSession().getNamedQuery(queryName);
		q.setFirstResult(firstResult);
		q.setMaxResults(maxResults);
		return q;
	}


}
